package com.edfu.core.institutemgt.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Set;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.edfu.core.coursemgt.util.CourseMgtModelConverter;
import com.edfu.core.identitymgt.persistence.api.IIdentityMgtPersistence;
import com.edfu.core.identitymgt.persistence.entity.UserEnrollmentEntity;
import com.edfu.core.identitymgt.service.api.IIdentityMgtService;
import com.edfu.core.identitymgt.vo.UserEnrollment;
import com.edfu.core.institutemgt.persistence.api.IInstituteMgtPersistence;
import com.edfu.core.institutemgt.persistence.entity.AcadSemBatchRelnEntity;
import com.edfu.core.institutemgt.persistence.entity.AcadSemBranchRelnEntity;
import com.edfu.core.institutemgt.persistence.entity.AcadSemEntity;
import com.edfu.core.institutemgt.persistence.entity.BatchEntity;
import com.edfu.core.institutemgt.persistence.entity.BranchEntity;
import com.edfu.core.institutemgt.persistence.entity.InstituteEntity;
import com.edfu.core.institutemgt.persistence.entity.SectionMemberEntity;
import com.edfu.core.institutemgt.service.api.IInstituteMgtService;
import com.edfu.core.institutemgt.vo.AcademicSemester;
import com.edfu.core.institutemgt.vo.Batch;
import com.edfu.core.institutemgt.vo.BatchSemesterAssn;
import com.edfu.core.institutemgt.vo.Branch;
import com.edfu.core.institutemgt.vo.Institute;
import com.edfu.core.institutemgt.vo.Section;
import com.edfu.core.institutemgt.vo.SectionMember;
import com.edfu.core.util.EduServiceFactory;
import com.edfu.core.util.Response;

public class InstituteMgtServiceImpl implements IInstituteMgtService {
	
	private IIdentityMgtPersistence identityMgtPersistence;
	public void setIdentityMgtPersistence(IIdentityMgtPersistence identityMgtPersistence) {
		this.identityMgtPersistence = identityMgtPersistence;
	}
	
	private IInstituteMgtPersistence instituteMgtPersistence;
	public void setInstituteMgtPersistence(
			IInstituteMgtPersistence instituteMgtPersistence) {
		this.instituteMgtPersistence = instituteMgtPersistence;
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { RuntimeException.class })
	public Response addInstitute(Institute institute) {
		InstituteEntity ie = CourseMgtModelConverter.getInstituteEntity(institute) ;
		if ( ie.getParentInstitute() != null ) {
			//TODO
		}
		/*Set<InstituteMemberEntity> owners = new HashSet<InstituteMemberEntity>();
		InstituteMemberEntity owner = new InstituteMemberEntity();
		owner.setRole(identityMgtPersistence.getRole("ADMIN"));
		//Hardcoded temporarily
		owner.setMember(identityMgtPersistence.getUser("sahsharm"));
		owner.setAddedOn(Calendar.getInstance().getTime());
		owner.setInstitute(ie);
		owners.add(owner);
		ie.setMembers(owners);*/
		instituteMgtPersistence.persist(ie);
		
		Response r = new Response();
		r.setSuccessful(true);
		return r;
 	}
	
	@Override
	public Response updateInstitute(Institute institute) {
		Response r = new Response();
		r.setSuccessful(true);
		return r;
	}
	
	@Override
	public Response deleteInstitute(String instituteCode) {
		Response r = new Response();
		r.setSuccessful(true);
		return r;
	}
	
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { RuntimeException.class })
	public Response addBranch(Branch branch) {
		BranchEntity be = CourseMgtModelConverter.getBranchEntity(branch) ;
		if (be.getParentBranch() != null ) {
			//TODO
		}
		InstituteEntity ie = instituteMgtPersistence.getInstitute(branch.getInstitute().getCode());
		be.setInstitute((InstituteEntity)ie) ;
		instituteMgtPersistence.persist(be);
		
		Response r = new Response();
		r.setSuccessful(true);
		return r;
	}
	
	@Override
	public Response updateBranch(Branch branch) {
		Response r = new Response();
		r.setSuccessful(true);
		return r;
	}
	
	@Override
	public Response deleteBranch(String branchCode) {
		Response r = new Response();
		r.setSuccessful(true);
		return r;
	}
	
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { RuntimeException.class })
	public Response addBatch(Batch batch) {
		BatchEntity be = CourseMgtModelConverter.getBatchEntity(batch);
		BranchEntity bre = instituteMgtPersistence.getBranch(batch.getBranch().getCode());
		//be.setBranch(bre);
		instituteMgtPersistence.persist(be);
		
		IIdentityMgtService identityMgtService = EduServiceFactory.getIdentityMgtService();
		if ( batch.getSections() != null && batch.getSections().size() > 0) {
			for (Section section : batch.getSections()) {
				Set<SectionMember> sectionMembers = section.getMembers();
				if ( sectionMembers != null && sectionMembers.size() > 0) {
					for ( SectionMember sectionMember : sectionMembers ) {
						UserEnrollment userEnrollment = sectionMember.getUserEnrollment();
						//Check if the user is already enrolled , if not enroll the user
						UserEnrollmentEntity uee = identityMgtPersistence.getUserEnrollment(userEnrollment.getUser().getUserId(), userEnrollment.getRoleName());
						if ( uee == null ) {
							identityMgtService.enrollUser(userEnrollment);
							uee = identityMgtPersistence.getUserEnrollment(userEnrollment.getUser().getUserId(), userEnrollment.getRoleName());
						}	
						SectionMemberEntity sme = new SectionMemberEntity();
						sme.setAddedOn(new Date());
						sme.setSection(instituteMgtPersistence.getSection(section.getCode()));
						sme.setUserEnrollment(uee);
						instituteMgtPersistence.persist(sme);
					}
				}
			}
		}else {
			//Create an implicit section by default
			//TODO
		}
		
		Response r = new Response();
		r.setSuccessful(true);
		return r;
	}
	
	@Override
	public Response updateBatch(Batch batch) {
		Response r = new Response();
		r.setSuccessful(true);
		return r;
	}
	
	@Override
	public Response deleteBatch(String batchCode) {
		Response r = new Response();
		r.setSuccessful(true);
		return r;
	}
	
	@Override
	public Response associateSemestersToBranch(List<String> semesterCodes,
			String branchCode) {
		Response r = new Response();
		r.setSuccessful(true);
		return r;
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { RuntimeException.class })
	public Response associateSemesterToBranch(String semesterCode, String branchCode) {
		AcadSemEntity ase = instituteMgtPersistence.getSemester(semesterCode);
		BranchEntity be = instituteMgtPersistence.getBranch(branchCode) ;
		AcadSemBranchRelnEntity asbre = new AcadSemBranchRelnEntity();
		asbre.setBranch(be);
		asbre.setSemester(ase);
		instituteMgtPersistence.persist(asbre) ;
		
		Response r = new Response();
		r.setSuccessful(true);
		return r;
	}
	
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { RuntimeException.class })
	public Response assignBatchToSemester(BatchSemesterAssn batchSemAssn) {
		BatchEntity be = instituteMgtPersistence.getBatch(batchSemAssn.getBatchCode());
		AcadSemEntity ase = instituteMgtPersistence.getSemester(batchSemAssn.getSemesterCode()) ;
		AcadSemBatchRelnEntity asbre = new AcadSemBatchRelnEntity();
		asbre.setBatch(be);
		asbre.setSemester(ase) ;
		instituteMgtPersistence.persist(asbre);
		
		Response r = new Response();
		r.setSuccessful(true);
		return r;
	}
	
	@Override
	public Response editBatchSemesterAssociation(String batchCode,
			String semesterCode, Date startsOn, Date endsOn) {
		Response r = new Response();
		r.setSuccessful(true);
		return r;
	}
	
	@Override
	public Institute getInstituteDetails(String instituteCode) {
		InstituteEntity ie = instituteMgtPersistence.getInstitute(instituteCode);
		return CourseMgtModelConverter.getInstituteVO(ie);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { RuntimeException.class })
	public Response addSemester(AcademicSemester semester) {
		AcadSemEntity ase = CourseMgtModelConverter.getSemesterEntity(semester);
		instituteMgtPersistence.persist(ase);
		
		Response r = new Response();
		r.setSuccessful(true);
		return r;
	}

}
